package com.sayimo.maker.mall.search.service.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.response.UpdateResponse;
import org.springframework.stereotype.Service;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.sayimo.framework.exception.DaoException;
import com.sayimo.framework.exception.ServiceException;
import com.sayimo.maker.commons.Constant;
import com.sayimo.maker.commons.utils.JSONUtil;
import com.sayimo.maker.commons.utils.SearchUtil;
import com.sayimo.maker.mall.search.dao.SearchDao;
import com.sayimo.maker.mall.search.service.SearchService;
import com.sayimo.maker.mall.search.vo.SearchField;
import com.sayimo.maker.mall.search.vo.SearchInsertParam;

/**
 * @Copyright (c) 2016 广东省尚一互联网有限公司
 * @Project: maker-mall
 * @ClassName: SearchServiceImpl.java
 * @Description: 
 * @Author:	tanxin
 * @Date:2017年2月13日,上午10:21:55
 * @Version 1.0.0
 */
@Service("searchService")
public class SearchServiceImpl implements SearchService {
	
	private static Log logger = LogFactory.getLog(SearchServiceImpl.class);
	
	@Resource(name="searchDao")
	private SearchDao searchDao;
	
	private static final String IDENTIFIER_COMMON_GOODS = "COMMON_GOODS";
	
	private static final String TYPE_COMMONS = "COMMONS";
	
	private static final String TYPE_ACTIVITY = "ACTIVITY";
	
	private static final String TYPE_MOLDBABY = "MOLDBABY";
	
	/** 
	  * @package com.sayimo.school.mall.module.search.service
	  * @author chenpy
	  * @Title:  
	  * @Description: 
	  * @param 
	  * @throws 
	  * @return Map<String,Object>
	  * @date 2016年8月6日
	  */ 
	public Map<String, Object> insertSearchEngine(SearchInsertParam searchInsertParam) throws ServiceException {
		logger.info("param = " + JSONUtil.writeValueAsString(searchInsertParam));
		logger.info("start insert engine = " + new Date());
		Map<String, Object> resultMap = new HashMap<>();
		UpdateResponse updateResponse = null;
		List<SearchField> fields = null;
		try{
			SolrServer solrServer = SearchUtil.getSolrServer();
			// 普通商品
			if (searchInsertParam.getGoodsType() == null || String.valueOf(searchInsertParam.getGoodsType()).equals("1")) {
				fields = searchDao.queryCommonGoodsEngineField(buildParamMap(searchInsertParam));
				// logger.info(JSONUtil.writeValueAsString(fields));
				// logger.info(fields);
			}
		
			// 活动商品
			if (searchInsertParam.getGoodsType() != null && (String.valueOf(searchInsertParam.getGoodsType()).equals("2") || 
					String.valueOf(searchInsertParam.getGoodsType()).equals("4"))) {
				Map<String, Object> paramMap = buildParamMap(searchInsertParam);
				paramMap.put("goodsType", searchInsertParam.getGoodsType());
				fields = searchDao.queryActivityGoodsEngineField(paramMap);
				// logger.info(fields);
			}
			
			// 爆款商品
			if (searchInsertParam.getGoodsType() != null && String.valueOf(searchInsertParam.getGoodsType()).equals("3")) {
				fields = searchDao.queryMoldbabyGoodsEngineField(buildParamMap(searchInsertParam));
				// logger.info(fields);
			}
			
			if (CollectionUtils.isNotEmpty(fields)) {
				updateResponse = solrServer.addBeans(fields);
				
				if (updateResponse == null || updateResponse.getStatus() != 0) {
					resultMap.put(Constant.STATUS, Constant.STATUS_ERROR);
					resultMap.put(Constant.ERROR_CODE, Constant.SYSTEM_ERROR);
					return resultMap;
				}
				solrServer.commit();
			}
			
		}catch(DaoException | SolrServerException | IOException e){
			logger.error(e);
			throw new ServiceException(e);
		}
		
		logger.info("end insert engine = " + new Date());
		resultMap.put(Constant.STATUS, Constant.STATUS_SUCCESS);
		return resultMap;
	}

	/** 
	  * @package com.sayimo.school.mall.module.search.service
	  * @author chenpy
	  * @Title:  
	  * @Description: 
	  * @param _ids
	  * @param _identifier
	  * @throws 
	  * @return Map<String,Object>
	  * @date 2016年8月6日
	  */ 
	public Map<String, Object> deleteSearchEngine(String _ids, String _identifier) throws ServiceException {
		Map<String, Object> resultMap = new HashMap<>();
		List<String> list = new ArrayList<>();
		JsonParser jsonParser = new JsonParser();
		logger.info("ids = " + _ids);
		JsonElement element = jsonParser.parse(_ids);
		
		if (element.isJsonArray()) {
			JsonArray array =element.getAsJsonArray();
			for (JsonElement jsonElement : array) {
				int goodsId = jsonElement.getAsInt();
				list.add(new StringBuilder(_identifier).append("_").append(goodsId).toString());
			}
		}
		else{
			String id = element.getAsString();
			if (!id.equals("*")) {
				list.add(new StringBuilder(_identifier).append("_").append(id).toString());
			}
		}
		
		UpdateResponse response = null;
		try{
			SolrServer solrServer = SearchUtil.getSolrServer();
			if (CollectionUtils.isNotEmpty(list)) {
				response = solrServer.deleteById(list);
			}else{
				response = solrServer.deleteByQuery("*:*");
			}
			
			if (response.getStatus() != 0) {
				resultMap.put(Constant.STATUS, Constant.STATUS_ERROR);
				resultMap.put(Constant.ERROR_CODE, Constant.SYSTEM_ERROR);
				return resultMap;
			}
			
			solrServer.commit();
		}catch(SolrServerException | IOException e){
			logger.error(e);
			throw new ServiceException(e);
		}
		
		resultMap.put(Constant.STATUS, Constant.STATUS_SUCCESS);
		return resultMap;
	}
	
	/** 
	  * @package com.sayimo.school.mall.module.search.service.imp
	  * @author chenpy
	  * @Title:  
	  * @Description: 
	  * @param 
	  * @throws 
	  * @return Map<String,Object>
	  * @date 2016年8月6日
	  */ 
	private Map<String, Object> buildParamMap(SearchInsertParam searchInsertParam){
		Map<String, Object> paramMap = new HashMap<>();
		Integer goodsIds[] = new Integer[0];
		
		paramMap.put("identifier", IDENTIFIER_COMMON_GOODS);
		if (StringUtils.isNotEmpty(searchInsertParam.getValue())) {
			JsonParser jsonParser = new JsonParser();
			JsonElement element = jsonParser.parse(searchInsertParam.getValue());
			if (element.isJsonArray()) {
				JsonArray array = element.getAsJsonArray();
				for (JsonElement jsonElement : array) {
					goodsIds = (Integer[]) ArrayUtils.add(goodsIds, jsonElement.getAsInt());
				}
			}else{
				goodsIds = (Integer[]) ArrayUtils.add(goodsIds, element.getAsInt());
			}
		}
		
		if (StringUtils.isNotEmpty(searchInsertParam.getIdentifier())) {
			paramMap.put("identifier", searchInsertParam.getIdentifier());
		}
		if (ArrayUtils.isNotEmpty(goodsIds)) {
			paramMap.put("goodsIds", goodsIds);
		}
		
		return paramMap;
	}
	
	/**
	  * 初始化
	  * @package com.sayimo.school.mall.module.search.service.imp
	  * @author chenpy
	  * @Title:  
	  * @Description: 
	  * @param 
	  * @throws 
	  * @return Map<String,Object>
	  * @date 2016年8月8日
	 */
	@SuppressWarnings("unused")
	public Map<String, Object> init(SearchInsertParam searchInsertParam) throws ServiceException{
		Map<String, Object> resultMap = new HashMap<>();
		try{
			UpdateResponse updateResponse = null;
			SolrServer server = SearchUtil.getSolrServer();
			if (searchInsertParam.getGoodsType() != null) {
				if (String.valueOf(searchInsertParam.getGoodsType()).equals("1")) {
					updateResponse = server.deleteByQuery(new StringBuffer("type:").append(TYPE_COMMONS).toString());
					searchInsertParam.setGoodsType(1);
					return insertSearchEngine(searchInsertParam);
				}else if(String.valueOf(searchInsertParam.getGoodsType()).equals("2")){
					String delQuery = StringUtils.isNotEmpty(searchInsertParam.getIdentifier()) ? (new StringBuffer("identifier:").append(searchInsertParam.getIdentifier())).toString() 
							: (new StringBuffer("type:").append(TYPE_ACTIVITY)).toString();
					updateResponse = server.deleteByQuery(delQuery);
					server.commit();
					return initActivityGoods(searchInsertParam);
				}else if(String.valueOf(searchInsertParam.getGoodsType()).equals("3")){
					String delQuery = StringUtils.isNotEmpty(searchInsertParam.getIdentifier()) ? (new StringBuffer("identifier:").append(searchInsertParam.getIdentifier())).toString() 
							: (new StringBuffer("type:").append(TYPE_MOLDBABY)).toString();
					updateResponse = server.deleteByQuery(delQuery);
					server.commit();
					return insertMoldBaby(searchInsertParam);
				}
				
				if (updateResponse != null && updateResponse.getStatus() == 0) {
					server.commit();
				}
			}else{
				deleteSearchEngine("*", "");
				
				searchInsertParam.setGoodsType(1);
				insertSearchEngine(searchInsertParam);
				
				initActivityGoods(searchInsertParam);
				insertMoldBaby(searchInsertParam);
			}
			
			server.optimize();
			resultMap.put(Constant.STATUS, Constant.STATUS_SUCCESS);
		}catch(ServiceException | SolrServerException | IOException e){
			logger.error(e);
			throw new ServiceException(e);
		}
		return resultMap;
	}
	
	private Map<String, Object> initActivityGoods(SearchInsertParam insertParam) throws ServiceException{
		SearchInsertParam searchInsertParam = new SearchInsertParam();
		Map<String, Object> resultMap = new HashMap<>();
		try{
			Map<String, Object> paramMap = new HashMap<>();
			paramMap.put("identifier", insertParam.getIdentifier());
			List activities = searchDao.queryAllActivity(paramMap);
			if (CollectionUtils.isEmpty(activities)) {
				resultMap.put(Constant.STATUS, Constant.STATUS_SUCCESS);
				return resultMap;
			}
			
			for (Object object : activities) {
				Map activityMap = (Map) object;
				Integer goodsType = (Integer) activityMap.get("goodsType");
				String identifier = (String) activityMap.get("identifier");
				searchInsertParam.setIdentifier(identifier);
				searchInsertParam.setGoodsType(goodsType == 0 ? 4 : 2);
				insertSearchEngine(searchInsertParam);
			}
			resultMap.put(Constant.STATUS, Constant.STATUS_SUCCESS);
			return resultMap;
		}catch(DaoException | ServiceException e){
			logger.error(e);
			throw new ServiceException(e);
		}
	}
	
	/** 
	  * @package com.sayimo.school.mall.module.search.service.imp
	  * @author chenpy
	  * @Title:  
	  * @Description: 
	  * @param 
	  * @throws 
	  * @return Map<String,Object>
	  * @date 2016年8月8日
	  */ 
	public Map<String, Object> insertMoldBaby(SearchInsertParam insertParam) throws ServiceException{
		SearchInsertParam searchInsertParam = new SearchInsertParam();
		Map<String, Object> resultMap = new HashMap<>();
		try{
			Map<String, Object> paramMap = new HashMap<>();
			paramMap.put("identifier", insertParam.getIdentifier());
			List moldBabies = searchDao.queryAllMoldBaby(paramMap);
			if (CollectionUtils.isEmpty(moldBabies)) {
				resultMap.put(Constant.STATUS, Constant.STATUS_SUCCESS);
				return resultMap;
			}
			
			for (Object object : moldBabies) {
				Map moldBabyMap = (Map) object;
				String identifier = (String) moldBabyMap.get("identifier");
				searchInsertParam.setIdentifier(identifier);
				searchInsertParam.setGoodsType(3);
				insertSearchEngine(searchInsertParam);
			}
			resultMap.put(Constant.STATUS, Constant.STATUS_SUCCESS);
			return resultMap;
		}catch(DaoException | ServiceException e){
			logger.error(e);
			throw new ServiceException(e);
		}
	}
}
